/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package src.view.loan;

import java.io.Serializable;
import java.math.BigDecimal;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.model.SelectItem;
import org.primefaces.context.RequestContext;
import org.primefaces.event.CloseEvent;
import src.domain.gl.Glaccnt;
import src.domain.loan.Loanprod;
import src.domain.loan.Loanprodcoral;
import src.domain.loan.Loanprodfee;
import src.domain.loan.Loanprodrate;
import src.services.gl.GlaccntConverter;
import src.services.gl.GlaccntModel;
import src.services.gl.TaxModel;
import src.services.loan.CollateralModel;
import src.services.loan.LoanfeeModel;
import src.services.loan.LoanprodModel;
import src.util.Messager;
import src.util.Utils;

/**
 *
 * @author jay
 */
@ManagedBean
@ViewScoped
public class LoanprodBean implements Serializable {

    private List<Loanprod> loanprods; //root
    private List<SelectItem> avaibleGL, avaibleTax, avaibleCoral, avaibleFee;
    private Loanprod selectedData, unsaveData;
    private Loanprodrate unsaveProdrate;
    private Loanprodcoral prodcoral;
    private Loanprodfee prodfee;
    private Glaccnt principalGL, interestGL, discIntrGL, accruedIntrGL, intrIncomeGL, 
            accruedPenaltyGL, penaltyIncomeGL, feeIncomeGL, woPrincipleGL, woIntrGL, woPenaltyGL;
    private List<Glaccnt> avblGL; 
    private Integer colateralId, feeId;
    private LoanprodModel helper;
    private LoanfeeModel feeHelper;
    private GlaccntModel glHelper;
    private TaxModel taxHelper;
    private CollateralModel coralHelper;
    private boolean editMode = true, editDetailMode=true;
    private int rateIdx;
    
    
    public LoanprodBean() {
        this.helper = new LoanprodModel();
        this.loanprods = helper.findAll(null);
        this.selectedData = null;
        this.unsaveData = null;
    }
    
    public boolean isEditMode() {
        return editMode;
    }
    
    public List<Loanprod> getLoanprods() {
        return this.loanprods;
    }
           
    public Loanprod getSelectedData() {
        return selectedData;
    }
    
    public void setSelectedData(Loanprod selectedData) {
        this.selectedData = selectedData;
    }

    public Loanprod getUnsaveData() {
        return unsaveData;
    }

    public void setUnsaveData(Loanprod unsaveData) {
        this.unsaveData = unsaveData;
    }

    public Loanprodcoral getProdcoral() {
        return prodcoral;
    }

    public void setProdcoral(Loanprodcoral prodcoral) {
        this.prodcoral = prodcoral;
    }

    public Loanprodrate getUnsaveProdrate() {
        return unsaveProdrate;
    }

    public void setUnsaveProdrate(Loanprodrate unsaveProdrate) {
        this.unsaveProdrate = unsaveProdrate;
    }
    
    public List<SelectItem> getAvaibleGL() {
        return avaibleGL;
    }

    public List<SelectItem> getAvaibleTax() {
        return avaibleTax;
    }

    public List<SelectItem> getAvaibleCoral() {
        return avaibleCoral;
    }

    public List<SelectItem> getAvaibleFee() {
        return avaibleFee;
    }

    public Integer getColateralId() {
        return colateralId;
    }

    public void setColateralId(Integer colateralId) {
        this.colateralId = colateralId;
    }

    public Integer getFeeId() {
        return feeId;
    }

    public void setFeeId(Integer feeId) {
        this.feeId = feeId;
    }

    public Loanprodfee getProdfee() {
        return prodfee;
    }

    public void setProdfee(Loanprodfee prodfee) {
        this.prodfee = prodfee;
    }
    
    public String selectItemValueOf(List<SelectItem> avblList, Integer id) {
        return (String) Utils.selectItemValueOf(avblList, id);
    }
    
    public void initForm() {
        this.coralHelper = new CollateralModel();
        this.glHelper = new GlaccntModel();
        this.taxHelper = new TaxModel();
        this.feeHelper = new LoanfeeModel();
        this.avaibleCoral = coralHelper.listAll();
        this.avaibleTax = taxHelper.listAll();
        this.avaibleGL = glHelper.listAll();
        this.avaibleFee = feeHelper.listAll();
        this.avblGL = GlaccntConverter.glaccountDB;
    }
        
    public void handleClose(CloseEvent event) {
        this.coralHelper = null;
        this.glHelper = null;
        this.taxHelper = null;
        this.feeHelper = null;
        this.selectedData = null;
        this.unsaveData = null;
        this.editMode = true;     
    }
        
    private void removeEmptyRate(){
        for(int i = 0; i<unsaveData.getLoanprodrates().size(); i++){
           BigDecimal interest = unsaveData.getLoanprodrates().get(i).getInterestRate();
           
           if(interest==null || (interest.compareTo(BigDecimal.valueOf(0)) < 1)) {
               unsaveData.getLoanprodrates().remove(i);
               i--;
           }
        }
    }
    
    private void removeEmptyCoral(){
        for(int i = 0; i<unsaveData.getLoanprodcorals().size(); i++){
            if(unsaveData.getLoanprodcorals().get(i).getCollateralId() == null ) {
                unsaveData.getLoanprodcorals().remove(i);
                i--;
            }
        }
    }
    
    private void removeEmptyFee(){
        for(int i = 0; i<unsaveData.getLoanprodfees().size(); i++){
            if(unsaveData.getLoanprodfees().get(i).getFeeId() == null ) {
                unsaveData.getLoanprodfees().remove(i);
                i--;
            }
        }
    }
    
    public void handleRemoveDetailRate() {  
        if (unsaveData.getLoanprodrates().size() == 1) unsaveData.getLoanprodrates().add(new Loanprodrate());
    }
    
    public void handleRemoveDetailCoral() {  
        if (unsaveData.getLoanprodcorals().size() == 1) unsaveData.getLoanprodcorals().add(new Loanprodcoral());
    }
    
    public void handleRemoveDetailFee() {  
        if (unsaveData.getLoanprodfees().size() == 1) unsaveData.getLoanprodfees().add(new Loanprodfee());
    }
        
    public void newDetailRate() {
        this.unsaveProdrate = new Loanprodrate();
        editDetailMode = false;
    }
    
    public void newDetailCoral() {
        this.prodcoral = new Loanprodcoral();
        editDetailMode = false;
    }
    
    public void newDetailFee() {
        this.prodfee = new Loanprodfee();
        editDetailMode = false;
    }
        
    public void editDetailRate(Loanprodrate data) {
        this.rateIdx = unsaveData.getLoanprodrates().indexOf(data);
        this.unsaveProdrate = Loanprodrate.clone(data);
        editDetailMode = true;
    }
    
    public void editDetailCoral(Loanprodcoral data) {
        this.prodcoral = data;
        this.colateralId = data.getCollateralId();
        editDetailMode = true;
    }
    
    public void editDetailFee(Loanprodfee data) {
        this.prodfee = data;
        this.feeId = data.getFeeId();
        editDetailMode = true;
    }
    
    public void saveDetailRate() {
        boolean success=true;
        try {
            if(!editDetailMode) {
                this.unsaveData.getLoanprodrates().add(unsaveProdrate);
                removeEmptyRate();
                
            } else unsaveData.getLoanprodrates().set(rateIdx, Loanprodrate.clone(unsaveProdrate));

        } catch (RuntimeException e) {success=false;
        } finally {Messager.showSaveUpdateStatus(success);}
    }
    
    
    public void saveDetailCoral() {
        boolean success=true;
        try {
            this.prodcoral.setCollateralId(colateralId);
            if(!editDetailMode) {
                this.unsaveData.getLoanprodcorals().add(prodcoral);
                removeEmptyCoral();    
            }
        } catch (RuntimeException e) {success=false;
        } finally {Messager.showSaveUpdateStatus(success);}
    }
    
    public void saveDetailFee() {
        boolean success=true;
        try {
            this.prodfee.setFeeId(feeId);
            if(!editDetailMode) {
                this.unsaveData.getLoanprodfees().add(prodfee);
                removeEmptyFee();                
            }
        } catch (RuntimeException e) {success=false;
        } finally {Messager.showSaveUpdateStatus(success);}
    }
    
    public void newData() {  
        initForm();
        this.editMode = false;
        this.selectedData = null;
        this.unsaveData = new Loanprod();
        this.unsaveData.getLoanprodrates().add(new Loanprodrate());
        this.unsaveData.getLoanprodcorals().add(new Loanprodcoral());
        this.unsaveData.getLoanprodfees().add(new Loanprodfee());
        
        this.interestGL= new Glaccnt(); 
        this.principalGL= new Glaccnt(); 
        this.discIntrGL= new Glaccnt();  
        this.accruedIntrGL= new Glaccnt(); 
        this.intrIncomeGL= new Glaccnt(); 
        this.accruedPenaltyGL= new Glaccnt(); 
        this.penaltyIncomeGL= new Glaccnt(); 
        this.feeIncomeGL= new Glaccnt(); 
        this.woPrincipleGL= new Glaccnt(); 
        this.woIntrGL= new Glaccnt(); 
        this.woPenaltyGL= new Glaccnt(); 
            
    }
    
    public void openData() {
        initForm();
        this.editMode = true;
        this.unsaveData = Loanprod.clone(selectedData);
        
        if (unsaveData.getLoanprodrates().isEmpty()) 
            this.unsaveData.getLoanprodrates().add(new Loanprodrate());
        
        if (unsaveData.getLoanprodcorals().isEmpty()) 
            this.unsaveData.getLoanprodcorals().add(new Loanprodcoral());
                
        if (unsaveData.getLoanprodfees().isEmpty()) 
            this.unsaveData.getLoanprodfees().add(new Loanprodfee());
        
        if (unsaveData.getPrincipalGlaccntId() != null)     this.principalGL= glHelper.getById(unsaveData.getPrincipalGlaccntId()); 
        if (unsaveData.getInterestGlaccntId() != null)      this.interestGL= glHelper.getById(unsaveData.getInterestGlaccntId()); 
        if (unsaveData.getDiscIntrGlaccntId() != null)      this.discIntrGL= glHelper.getById(unsaveData.getDiscIntrGlaccntId()); 
        if (unsaveData.getAccruedIntrGlaccntId() != null)   this.accruedIntrGL= glHelper.getById(unsaveData.getAccruedIntrGlaccntId()); 
        if (unsaveData.getIntrIncomeGlaccntId() != null)    this.intrIncomeGL= glHelper.getById(unsaveData.getIntrIncomeGlaccntId()); 
        if (unsaveData.getAccruedPenaltyGlaccntId() != null) this.accruedPenaltyGL= glHelper.getById(unsaveData.getAccruedPenaltyGlaccntId()); 
        if (unsaveData.getPenaltyIncomeGlaccntId() != null) this.penaltyIncomeGL= glHelper.getById(unsaveData.getPenaltyIncomeGlaccntId()); 
        if (unsaveData.getFeeIncomeGlaccntId() != null)     this.feeIncomeGL= glHelper.getById(unsaveData.getFeeIncomeGlaccntId()); 
        if (unsaveData.getWoPrincipleGlaccntId() != null)   this.woPrincipleGL= glHelper.getById(unsaveData.getWoPrincipleGlaccntId()); 
        if (unsaveData.getWoIntrGlaccntId() != null)        this.woIntrGL= glHelper.getById(unsaveData.getWoIntrGlaccntId()); 
        if (unsaveData.getWoPenaltyGlaccntId() != null)     this.woPenaltyGL= glHelper.getById(unsaveData.getWoPenaltyGlaccntId()); 
    }
    
    private boolean validate() {
        boolean hasil = true;
        boolean productExist;
        removeEmptyCoral();
        removeEmptyFee();
        removeEmptyRate();
        
        if (unsaveData.getLoanprodrates().isEmpty()) {
            hasil = false;
            
            Messager.showWarning("intRateRequired");
        }
        
        productExist = helper.isProductExist(unsaveData.getProductNo(), unsaveData.getLoanprodId());
        if (productExist==true) {
            Messager.showError("codeIsExist");
             hasil = false;
        }
        
        //biar ada row lagi, jadi bisa edit-insert
        if (hasil==false) {
            if (unsaveData.getLoanprodrates().isEmpty()) this.unsaveData.getLoanprodrates().add(new Loanprodrate());
            if (unsaveData.getLoanprodcorals().isEmpty()) this.unsaveData.getLoanprodcorals().add(new Loanprodcoral());
            if (unsaveData.getLoanprodfees().isEmpty()) this.unsaveData.getLoanprodfees().add(new Loanprodfee());
            
        }
        return hasil;
    }
    
    public void trySave() {
        if(this.validate()) save();
    }
    
    private void save() {
        RequestContext context = RequestContext.getCurrentInstance();
                
        unsaveData.setInterestGlaccntId(interestGL.getGlaccntId()); 
        unsaveData.setDiscIntrGlaccntId(discIntrGL.getGlaccntId()); 
        unsaveData.setAccruedIntrGlaccntId(accruedIntrGL.getGlaccntId()); 
        unsaveData.setIntrIncomeGlaccntId(intrIncomeGL.getGlaccntId()); 
        unsaveData.setAccruedPenaltyGlaccntId(accruedPenaltyGL.getGlaccntId());  
        unsaveData.setPenaltyIncomeGlaccntId(penaltyIncomeGL.getGlaccntId()); 
        unsaveData.setFeeIncomeGlaccntId(feeIncomeGL.getGlaccntId()); 
        unsaveData.setWoPrincipleGlaccntId(woPrincipleGL.getGlaccntId()); 
        unsaveData.setWoIntrGlaccntId(woIntrGL.getGlaccntId()); 
        unsaveData.setWoPenaltyGlaccntId(woPenaltyGL.getGlaccntId()); 
        unsaveData.setPrincipalGlaccntId(principalGL.getGlaccntId()); 
        
        boolean success = helper.saveData(unsaveData);
        if (success==true) {
            if (this.editMode==false) this.loanprods.add(unsaveData);
            else {
                int i = loanprods.indexOf(selectedData);
                if (i <= loanprods.size()) loanprods.set(i, Loanprod.clone(unsaveData));
            }
            editMode = true;
            
        } else {
            if (this.editMode==false) unsaveData.setLoanprodId(null);
        }
        
        Messager.showSaveUpdateStatus(success);        
        context.addCallbackParam("success", success);  
    }
    
    public void delete() {
        RequestContext context = RequestContext.getCurrentInstance();  
                
        boolean success = helper.deleteData(this.selectedData);
        
        if (success) {
            this.loanprods.remove(this.selectedData);
            this.selectedData = null;
        } 
        Messager.showDeleteStatusConstaint(success);  
        context.addCallbackParam("success", success);  
    }

    public Glaccnt getAccruedIntrGL() {
        return accruedIntrGL;
    }

    public Glaccnt getAccruedPenaltyGL() {
        return accruedPenaltyGL;
    }

    public List<Glaccnt> getAvblGL() {
        return avblGL;
    }

    public Glaccnt getDiscIntrGL() {
        return discIntrGL;
    }

    public Glaccnt getFeeIncomeGL() {
        return feeIncomeGL;
    }

    public Glaccnt getInterestGL() {
        return interestGL;
    }

    public Glaccnt getIntrIncomeGL() {
        return intrIncomeGL;
    }

    public Glaccnt getPenaltyIncomeGL() {
        return penaltyIncomeGL;
    }

    public Glaccnt getWoIntrGL() {
        return woIntrGL;
    }

    public Glaccnt getWoPenaltyGL() {
        return woPenaltyGL;
    }

    public Glaccnt getWoPrincipleGL() {
        return woPrincipleGL;
    }

    public Glaccnt getPrincipalGL() {
        return principalGL;
    }

    public void setPrincipalGL(Glaccnt principalGL) {
        this.principalGL = principalGL;
    }

    public void setAccruedIntrGL(Glaccnt accruedIntrGL) {
        this.accruedIntrGL = accruedIntrGL;
    }

    public void setAccruedPenaltyGL(Glaccnt accruedPenaltyGL) {
        this.accruedPenaltyGL = accruedPenaltyGL;
    }

    public void setDiscIntrGL(Glaccnt discIntrGL) {
        this.discIntrGL = discIntrGL;
    }

    public void setFeeIncomeGL(Glaccnt feeIncomeGL) {
        this.feeIncomeGL = feeIncomeGL;
    }

    public void setInterestGL(Glaccnt interestGL) {
        this.interestGL = interestGL;
    }

    public void setIntrIncomeGL(Glaccnt intrIncomeGL) {
        this.intrIncomeGL = intrIncomeGL;
    }

    public void setPenaltyIncomeGL(Glaccnt penaltyIncomeGL) {
        this.penaltyIncomeGL = penaltyIncomeGL;
    }

    public void setWoIntrGL(Glaccnt woIntrGL) {
        this.woIntrGL = woIntrGL;
    }

    public void setWoPenaltyGL(Glaccnt woPenaltyGL) {
        this.woPenaltyGL = woPenaltyGL;
    }

    public void setWoPrincipleGL(Glaccnt woPrincipleGL) {
        this.woPrincipleGL = woPrincipleGL;
    }
    
    
    
    
}
